package com.agileboot.attendance.domain.personnel;

import com.agileboot.attendance.constants.AttendanceConstants;
import com.agileboot.attendance.domain.personnel.command.AddPersonnelCommand;
import com.agileboot.attendance.domain.personnel.command.UpdatePersonnelCommand;
import com.agileboot.attendance.domain.personnel.db.AttPersonnelEntity;
import com.agileboot.attendance.domain.personnel.db.AttPersonnelService;
import com.agileboot.attendance.domain.personnel.dto.PersonnelDTO;
import com.agileboot.attendance.domain.personnel.dto.SearchPersonnelDTO;
import com.agileboot.attendance.domain.personnel.model.PersonnelModel;
import com.agileboot.attendance.domain.personnel.model.PersonnelModelFactory;
import com.agileboot.attendance.domain.supplier.db.AttSupplierEntity;
import com.agileboot.attendance.domain.supplier.db.AttSupplierService;
import com.agileboot.attendance.domain.supplier.dto.SupplierOptionDTO;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.common.core.page.PageQuery;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.common.utils.poi.ExportImportService;
import com.agileboot.common.core.command.BulkOperationCommand;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

/**
 * <p>
 * 人员应用服务类
 * </p>
 *
 * @author agileboot
 * @since 2023-03-14
 */
@Service
@RequiredArgsConstructor
public class PersonnelApplicationService {

    private final AttPersonnelService personnelService;
    private final AttSupplierService supplierService;
    private final PersonnelModelFactory personnelModelFactory;
    private final ExportImportService exportImportService;

    /**
     * 获取人员分页列表
     *
     * @param query 查询参数
     * @return 分页结果
     */
    public PageDTO<PersonnelDTO> getPersonnelList(PageQuery<SearchPersonnelDTO> query) {
        Page<AttPersonnelEntity> page = personnelService.getPersonnelList(query);
        List<PersonnelDTO> personnelDTOList = page.getRecords().stream()
            .map(personnel -> {
                PersonnelDTO dto = new PersonnelDTO(personnel);
                if (personnel.getSupplierId() != null) {
                    dto.setSupplierName(supplierService.getById(personnel.getSupplierId()).getSupplierName());
                }
                return dto;
            })
            .collect(Collectors.toList());

        return new PageDTO<>(personnelDTOList, page.getTotal());
    }

    /**
     * 根据ID获取人员详情
     *
     * @param personnelId 人员ID
     * @return 人员详情
     */
    public PersonnelDTO getPersonnelInfo(Long personnelId) {
        AttPersonnelEntity personnel = personnelService.getById(personnelId);
        return new PersonnelDTO(personnel, 
            personnel.getSupplierId() != null ? supplierService.getById(personnel.getSupplierId()) : null);
    }

    /**
     * 添加人员
     *
     * @param command 添加命令
     */
    @Transactional(rollbackFor = Exception.class)
    public void addPersonnel(AddPersonnelCommand command) {
        PersonnelModel model = personnelModelFactory.create();
        model.loadAddCommand(command);

        model.checkPersonnelCodeIsUnique();
        model.checkIdNumberIsUnique();
        model.checkPhoneNumberIsUnique();
        model.checkEmailIsUnique();
        model.checkRelatedEntityExist();

        model.insert();
    }

    /**
     * 更新人员
     *
     * @param command 更新命令
     */
    @Transactional(rollbackFor = Exception.class)
    public void updatePersonnel(UpdatePersonnelCommand command) {
        PersonnelModel model = personnelModelFactory.loadById(command.getPersonnelId());
        model.loadUpdateCommand(command);

        model.checkPersonnelCodeIsUnique();
        model.checkIdNumberIsUnique();
        model.checkPhoneNumberIsUnique();
        model.checkEmailIsUnique();
        model.checkRelatedEntityExist();

        model.updateById();
    }

    /**
     * 删除人员
     *
     * @param command 批量操作命令
     */
    @Transactional(rollbackFor = Exception.class)
    public void deletePersonnel(BulkOperationCommand<Long> command) {
        for (Long id : command.getItems()) {
            PersonnelModel model = personnelModelFactory.loadById(id);
            model.deleteById();
        }
    }
    
    /**
     * 导出人员数据
     *
     * @param searchPersonnelDTO 查询参数
     * @param response 响应对象
     */
    public void exportPersonnel(SearchPersonnelDTO searchPersonnelDTO, HttpServletResponse response) {
        try {
            // 查询所有满足条件的人员数据
            PageQuery<SearchPersonnelDTO> query = new PageQuery<>();
            query.setParam(searchPersonnelDTO);
            query.setPageSize(Integer.MAX_VALUE); // 不分页，导出全部
            query.setPageNum(1);
            
            Page<AttPersonnelEntity> page = personnelService.getPersonnelList(query);
            List<PersonnelDTO> personnelDTOList = page.getRecords().stream()
                .map(personnel -> {
                    PersonnelDTO dto = new PersonnelDTO(personnel);
                    if (personnel.getSupplierId() != null) {
                        dto.setSupplierName(supplierService.getById(personnel.getSupplierId()).getSupplierName());
                    }
                    return dto;
                })
                .collect(Collectors.toList());
            
            // 使用通用导出服务
            exportImportService.export(personnelDTOList, PersonnelDTO.class, response, "人员列表", "excel");
        } catch (Exception e) {
            throw new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "导出失败：" + e.getMessage());
        }
    }
    
    /**
     * 导入人员数据
     *
     * @param file Excel文件
     */
    @Transactional(rollbackFor = Exception.class)
    public void importPersonnel(MultipartFile file) {
        if (file.isEmpty()) {
            throw new ApiException(ErrorCode.Business.UPLOAD_FILE_IS_EMPTY);
        }
        
        try {
            // 使用通用导入服务
            List<AddPersonnelCommand> commands = exportImportService.importData(file, AddPersonnelCommand.class);
            
            // 批量添加人员
            for (AddPersonnelCommand command : commands) {
                addPersonnel(command);
            }
        } catch (Exception e) {
            throw new ApiException(ErrorCode.Business.UPLOAD_IMPORT_EXCEL_FAILED, e.getMessage());
        }
    }
    
    /**
     * 下载导入模板
     *
     * @param response 响应对象
     */
    public void downloadImportTemplate(HttpServletResponse response) {
        try {
            // 使用通用模板服务
            exportImportService.getImportTemplate(AddPersonnelCommand.class, response, "人员导入模板", "excel");
        } catch (Exception e) {
            throw new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "模板下载失败：" + e.getMessage());
        }
    }
    
    /**
     * 获取供应商下拉选项列表
     *
     * @return 供应商选项列表
     */
    public List<SupplierOptionDTO> getSupplierOptions() {
        return supplierService.lambdaQuery()
            .eq(AttSupplierEntity::getStatus, AttendanceConstants.SupplierStatus.NORMAL)
            .list()
            .stream()
            .map(supplier -> new SupplierOptionDTO(
                supplier.getSupplierId(),
                supplier.getSupplierName(),
                supplier.getSupplierCode(),
                supplier.getStatus()
            ))
            .collect(Collectors.toList());
    }
} 